package com.zhi.shiro;

import com.zhi.config.Constant;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import com.zhi.entity.User;
import com.zhi.service.UserService;

public class UserRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	
	// 授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		Subject subject=SecurityUtils.getSubject();
		User user=(User) subject.getPrincipal();
		SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addStringPermission(user.getUserType());//用户权限级别
		return simpleAuthorizationInfo;
	}

	// 身份验证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		
		//1获取token中的User，不再使用原生类UsernamePasswordToken，使用自定义的UserLoginToken
		UserLoginToken tokenUser = (UserLoginToken) token;

		//2准备用户校验数据，包括：用户名，密码，用户类型
		User realUser = new User(null, tokenUser.getUsername(), String.copyValueOf(tokenUser.getPassword()), tokenUser.getUserType(),Constant.EFFECTIVE_YES,null,null);
		
		//3查询数据库中账号密码类型匹配个数
		int res = userService.count(realUser);

		//4根据个数判断校验结果，账号或密码有误
		if (res < 1) {
			throw new UnknownAccountException("账号或密码不正确或用户已失效");
		}

		// 防止密码暴露
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(realUser, realUser.getPassword(), getName());
		return info;
	}

}
